package com.hw01.service.impl;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import com.hw01.mapper.OrganizationMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.hw01.common.Result;
import com.hw01.common.ResultPage;
import com.hw01.common.UserInfo;
import com.hw01.constant.DelState;
import com.hw01.constant.EmployeeUseState;
import com.hw01.dto.ChangePasswordDto;
import com.hw01.dto.EmployeeAddDto;
import com.hw01.dto.EmployeeQueryDto;
import com.hw01.dto.EmployeeUpdateDto;
import com.hw01.entity.Employee;
import com.hw01.entity.Organization;
import com.hw01.mapper.EmployeeMapper;
import com.hw01.service.EmployeeService;
import com.hw01.utils.OSSUtils;
import com.hw01.vo.EmployeeVo;
import com.hw01.vo.LoginUserVo;


/**
 * <p>
 * 员工用户表 服务实现类
 * </p>
 *
 * @author zhong
 * @since 2024-03-18
 */
@Service
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements EmployeeService {

    @Autowired
    private EmployeeMapper mapper;

    @Autowired
    private OrganizationMapper organizationMapper;

    @Override
    public Result<EmployeeVo> getEmployeeById(Long id) {

        Employee e = mapper.selectById(id);

        if (e == null || e.getDelState()) {
            return Result.error("没有查询到对应的用户");
        }

        EmployeeVo vo = new EmployeeVo();
        BeanUtils.copyProperties(e, vo);
        return Result.success("执行成功", vo);
    }

    @Override
    public Result<Boolean> changePassword(ChangePasswordDto dto) {
        if (dto == null) {
            return Result.error("输入参数错误");
        }

        Employee e = mapper.selectById(dto.getUserId());

        if (e == null || e.getDelState()) {
            return Result.error("没有查询到对应的用户");
        }

        if (!e.getPassword().equals(dto.getOldPassword())) {
            return Result.error("旧密码输入错误");
        }

        if (StringUtils.isBlank(dto.getNewPassword())) {
            return Result.error("请输入正确的新密码");
        }

        if (!dto.getNewPassword().equals(dto.getConfirmNewPassword())) {
            return Result.error("两次输入的新密码不一致");
        }

        LambdaUpdateWrapper<Employee> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(Employee::getPassword, dto.getNewPassword());
        updateWrapper.eq(Employee::getId, dto.getUserId());

        mapper.update(null, updateWrapper);

        return Result.success("修改密码成功");
    }

    @Override
    public ResultPage<EmployeeVo> getEmployeePage(EmployeeQueryDto dto) {

        Page<EmployeeVo> page = ResultPage.toQueryPage(dto.getPageQuery());

        // 查询条件
        MPJLambdaWrapper<Employee> wrapper = new MPJLambdaWrapper<Employee>().selectAll(Employee.class)
            .selectAs(Organization::getOrganizationName, Organization::getOrganizationName)
            // 部门条件
            .leftJoin(Organization.class, Organization::getId, Employee::getOrganizationId)
            // 部门id
            .eq(Objects.nonNull(dto.getOrganizationId()), Organization::getId, dto.getOrganizationId())

            // 员工条件
            .eq(Employee::getDelState, DelState.UNDELETED)
            .eq(Objects.nonNull(UserInfo.getOrgId()), Employee::getOrganizationId, UserInfo.getOrgId())
            // 排除管理账号
            .ne(Employee::getLoginName, "admin")
            // 地址
            .like(StringUtils.isNotBlank(dto.getAddress()), Employee::getAddress, dto.getAddress())
            // 电话
            .like(StringUtils.isNotBlank(dto.getPhone()), Employee::getPhone, dto.getPhone())
            // 登录用户名和用户名
            .and(StringUtils.isNotBlank(dto.getSearchName()),
                QueryWrapper -> QueryWrapper.like(Employee::getLoginName, dto.getSearchName()).or()
                    .like(Employee::getUserName, dto.getSearchName()));

        // 排序
        wrapper.orderByAsc(Employee::getId);

        mapper.selectJoinPage(page, EmployeeVo.class, wrapper);

        return ResultPage.fromPage(page);
    }

    @Override
    public Result<LoginUserVo> login(String loginName, String password) {

        Employee employee = getEmployeeByLoginName(loginName);

        if (employee == null || !employee.getPassword().equals(password)) {
            return Result.error("用户名或密码错误");
        }

        LoginUserVo loginUser = new LoginUserVo();
        BeanUtils.copyProperties(employee, loginUser);

        return Result.success("登录成功", loginUser);
    }

    @Override
    public Result<LoginUserVo> loginWeb(String loginName, String password) {
        Employee employee = getEmployeeByLoginNameWeb(loginName);

        if (employee == null || !employee.getPassword().equals(password)) {
            return Result.error("用户名或密码错误");
        }

        LoginUserVo loginUser = new LoginUserVo();

        BeanUtils.copyProperties(employee, loginUser);

        return Result.success("登录成功", loginUser);
    }

    @Override
    public Result<Boolean> add(EmployeeAddDto dto) {
        if (dto == null) {
            return Result.error("新增员工信息缺少必要信息");
        }

        String loginName = dto.getLoginName();
        if (StringUtils.isBlank(loginName)) {
            return Result.error("请填写员工登录用户名");
        }

        Employee employeeQuery = getEmployeeByLoginName(loginName);

        if (employeeQuery != null) {
            return Result.error("登录用户名已被使用");
        }

        Employee employee = new Employee();
        BeanUtils.copyProperties(dto, employee);

        // 设置默认值
        employee.setProfilePicture(OSSUtils.DEFAULT_PHOTO); // 默认头像
        employee.setUseState(EmployeeUseState.ACTIVE);
        employee.setDelState(DelState.UNDELETED);
        employee.setCreator(UserInfo.getUserId());
        employee.setCreateTm(LocalDateTime.now());
        employee.setModifier(UserInfo.getUserId());
        employee.setModifyTm(LocalDateTime.now());

        // 默认基本薪资
        if (employee.getBasicSalary() == null || employee.getBasicSalary().doubleValue() <= 0.0) {
            employee.setBasicSalary(new BigDecimal("3000.0"));
        }

        // 设置默认密码 123456
        if (StringUtils.isBlank(employee.getPassword())) {
            employee.setPassword("123456");
        }
        
        // 入职日期
        LocalDate dateOnBoard = dto.getDateOnBoard();
        if (dateOnBoard == null) {
            dateOnBoard = LocalDate.now();
        }
        employee.setDateOnBoard(dateOnBoard);

        mapper.insert(employee);

        return Result.success("新增员工成功", true);
    }

    @Override
    public Result<Boolean> update(EmployeeUpdateDto dto) {
        
        Employee employee = mapper.selectById(dto.getId());
        
        if (employee == null || employee.getDelState()) {
            return Result.error("没有查到员工信息，请刷新后重试", false);
        }

        String loginName = dto.getLoginName();
        if (StringUtils.isBlank(loginName)) {
            return Result.error("请填写员工登录用户名", false);
        }
        Employee employeeQuery = getEmployeeByLoginName(loginName);
        if (employeeQuery != null && !employeeQuery.getId().equals(dto.getId())) {
            return Result.error("登录用户名已被使用", false);
        }

        BigDecimal basicSalary = dto.getBasicSalary();
        // 默认基本薪资
        if (basicSalary == null || basicSalary.doubleValue() <= 0.0) {
            basicSalary = new BigDecimal("3000.0");
        }

        employee.setModifier(UserInfo.getUserId()).setModifyTm(LocalDateTime.now()).setBasicSalary(basicSalary)
            .setAddress(dto.getAddress()).setBirthDate(dto.getBirthDate()).setEmail(dto.getEmail())
            .setPhone(dto.getPhone()).setOrganizationId(dto.getOrganizationId()).setUserName(dto.getUserName())
            .setLoginName(dto.getLoginName()).setSex(dto.getSex());

        mapper.updateById(employee);

        return Result.success("修改员工信息成功", true);
    }

    @Override
    public Result<Boolean> delete(Long id) {
        // 不做校验，直接修改
        LambdaUpdateWrapper<Employee> updateWrapper = new LambdaUpdateWrapper<Employee>()
                .set(Employee::getDelState, DelState.DELETED)
                .set(Employee::getUseState, EmployeeUseState.DIMISSION)
                .set(Employee::getTermDate, LocalDate.now())
                .set(Employee::getModifier, UserInfo.getUserId())
                .set(Employee::getModifyTm, LocalDateTime.now())
                .eq(Employee::getId, id);

        mapper.update(null, updateWrapper);

        return Result.success("删除员工信息成功", true);
    }

    @Override
    public Result<String> uploadPhotoAvatar(Long userId, MultipartFile file) {
        // 文件名
        String fileName = file.getOriginalFilename();

        if (StringUtils.isBlank(fileName)) {
            return Result.error("输入的文件错误");
        }

        String[] fileNames = fileName.split("[.]");
        String suffix = fileNames[fileNames.length - 1];

        // oss路径，包括文件名
        String objectName = userId + "." + suffix;
        String url = null;
        try (InputStream is = file.getInputStream()) {
            // 上传到OSS
            url = OSSUtils.upload(is, objectName);
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (StringUtils.isNotBlank(url)) {
            LambdaUpdateWrapper<Employee> updateWrapper =
                new LambdaUpdateWrapper<Employee>().set(Employee::getProfilePicture, url).eq(Employee::getId, userId);
            mapper.update(null, updateWrapper);

            return Result.success("用户头像上传成功", url);
        } else {
            return Result.error("用户头像上传失败");
        }
    }

    @Override
    public Result<List<EmployeeVo>> getEmployeeByOrgId(Long orgId) {
        // 查询条件
        MPJLambdaWrapper<Employee> wrapper = new MPJLambdaWrapper<Employee>().selectAll(Employee.class)
            .selectAs(Organization::getOrganizationName, Organization::getOrganizationName)
            // 部门条件
            .leftJoin(Organization.class, Organization::getId, Employee::getOrganizationId)
            // 部门id
            .eq(Objects.nonNull(orgId), Organization::getId, orgId)

            // 员工条件
            .eq(Employee::getDelState, DelState.UNDELETED)
            // 排除管理账号
            .ne(Employee::getLoginName, "admin");

        // 排序
        wrapper.orderByAsc(Employee::getId);

        List<EmployeeVo> vo = mapper.selectJoinList(EmployeeVo.class, wrapper);

        return Result.success("登录成功", vo);
    }

    /**
     * 按登录用户名查询员工用户信息
     * 
     * @param loginName 登录用户名
     * @return Employee 员工用户信息
     */
    private Employee getEmployeeByLoginName(String loginName) {
        return mapper.selectOne(new LambdaQueryWrapper<Employee>().eq(Employee::getDelState, DelState.UNDELETED)
            .eq(Employee::getUseState, EmployeeUseState.ACTIVE).eq(Employee::getLoginName, loginName));
    }

    /**
     * 按登录用户名查询员工用户信息(网页)
     *
     * @param loginName 登录用户名
     * @return Employee 员工用户信息
     */
    private Employee getEmployeeByLoginNameWeb(String loginName) {

        // 部门
        List<Organization> orgList = organizationMapper.selectList(new LambdaQueryWrapper<Organization>().isNotNull(Organization::getLeaderId));
        
        // 部门领导
        List<Long> orgLeader = orgList.stream().map(Organization::getLeaderId).collect(Collectors.toList());

        return mapper.selectOne(new LambdaQueryWrapper<Employee>().eq(Employee::getDelState, DelState.UNDELETED)
            .eq(Employee::getUseState, EmployeeUseState.ACTIVE).eq(Employee::getLoginName, loginName)
            // 部门领导和管理员可以登录wab页面
            .and(QueryWrapper -> QueryWrapper.in(orgLeader.size() > 0, Employee::getId, orgLeader).or()
                .eq(Employee::getLoginName, "admin")));

    }

}
